package com.example.lin.togglebutton.view;

import android.annotation.SuppressLint;
import android.content.Context;
import android.util.AttributeSet;
import android.view.View;
import android.view.ViewGroup;

import java.util.ArrayList;
import java.util.List;

public class FlowLayout extends ViewGroup {

    /**
     * 重写该方法,子View 才可以使用 margin属性
     *
     * @param attrs
     * @return
     */
    @Override
    public LayoutParams generateLayoutParams(AttributeSet attrs) {
        return new MarginLayoutParams(getContext(), attrs);
    }

    public FlowLayout(Context context) {
        super(context);
    }

    public FlowLayout(Context context, AttributeSet attrs) {
        super(context, attrs);
    }


    /**
     * 一行View的封装
     */
    private class LineViews {
        List<View> views = new ArrayList<>();
        int lineWidth;//行宽
        int maxHeight;//行高

        void addView(View child) {
            views.add(child);
            MarginLayoutParams lp = (MarginLayoutParams) child.getLayoutParams();
            lineWidth += child.getMeasuredWidth() + lp.leftMargin + lp.rightMargin;
            maxHeight = Math.max(maxHeight, child.getMeasuredHeight() + lp.topMargin + lp.bottomMargin);
        }
    }

    private List<LineViews> lines = new ArrayList<>();//所有行

    /**
     * MeasureSpec.AT_MOST 当宽高为 wrap_content的时候
     * MeasureSpec.EXACTLY 当宽高为固定的时候(200dp,math_parent)
     * MeasureSpec.UNSPECIFIED ,当父容器是 ScrollView的时候
     *
     * @param widthMeasureSpec
     * @param heightMeasureSpec
     */
    @SuppressLint("DrawAllocation")
    @Override
    protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
        lines.clear();//当重新测量的时候.清空所有行
        final int specModeWidth = MeasureSpec.getMode(widthMeasureSpec);
        final int specSizeWidth = MeasureSpec.getSize(widthMeasureSpec);
        final int specModeHeight = MeasureSpec.getMode(heightMeasureSpec);
        final int specSizeHeight = MeasureSpec.getSize(heightMeasureSpec);
        //测量字view
        measureChildren(widthMeasureSpec, heightMeasureSpec);
        /********分析每一行布置哪几个View******/
        LineViews lineViews = new LineViews();
        for (int i = 0; i < getChildCount(); i++) {//2
            View child = getChildAt(i);
            MarginLayoutParams lp = (MarginLayoutParams) child.getLayoutParams();
            final int w = child.getMeasuredWidth() + lp.leftMargin + lp.rightMargin;
            if (w + lineViews.lineWidth > specSizeWidth) {
                lines.add(lineViews);//把当前行加入到 lines集合中
                lineViews = new LineViews();  //另起一行
            }
            lineViews.addView(child);
            if (i == getChildCount() - 1) {
                lines.add(lineViews);//把最后一行加入到 lines集合中
            }
        }
        /*************计算当宽高不确定的时候,自己测量的宽高***********/
        int maxLineWidth = 0;
        int sumHeight = 0;
        for (LineViews lv : lines) {
            maxLineWidth = Math.max(maxLineWidth, lv.lineWidth);
            sumHeight += lv.maxHeight;
        }
        /*************最终确定布局宽高***********/
        final int resultWidth = specModeWidth == MeasureSpec.EXACTLY ? specSizeWidth : maxLineWidth;
        final int resultHeight = specModeHeight == MeasureSpec.EXACTLY ? specSizeHeight : sumHeight;
        setMeasuredDimension(resultWidth, resultHeight);
    }

    @Override
    protected void onLayout(boolean changed, int l, int t, int r, int b) {
        int lineTop = 0;//确定每一行的顶部边缘位置(含margin值)
        for (LineViews lv : lines) {
            int lastChildRightScope = 0;//当前行的上一个View的右边缘(含margin值)
            List<View> views = lv.views;
            for (View child : views) {
                MarginLayoutParams lp = (MarginLayoutParams) child.getLayoutParams();
                int childTop = lineTop + lp.topMargin;
                int childLeft = lastChildRightScope + lp.leftMargin;
                int childBottom = childTop + child.getMeasuredHeight();
                int childRight = childLeft + child.getMeasuredWidth();
                child.layout(childLeft, childTop, childRight, childBottom);
                lastChildRightScope = childRight + lp.rightMargin;
            }
            lineTop += lv.maxHeight;
        }
    }
}
